/*
 *  Copyright (C) 2015, gelitenight(gelitenight@gmail.com).
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.novellotus.iov.carvice.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import com.novellotus.iov.carvice.R;

/**
 * 自定义波浪旋转充电组件
 */
public class WaveView extends View {
    /**
     * +------------------------+
     * |<--wave length->        |______
     * |   /\          |   /\   |  |
     * |  /  \         |  /  \  | amplitude
     * | /    \        | /    \ |  |
     * |/      \       |/      \|__|____
     * |        \      /        |  |
     * |         \    /         |  |
     * |          \  /          |  |
     * |           \/           | water level
     * |                        |  |
     * |                        |  |
     * +------------------------+__|____
     */
    private static float DEFAULT_AMPLITUDE_RATIO = 0.05f;
    private static float DEFAULT_WATER_LEVEL_RATIO = 0.5f;
    private static float DEFAULT_WAVE_LENGTH_RATIO = 1.0f;
    private static float DEFAULT_WAVE_SHIFT_RATIO = 0.0f;
    private float mAmplitudeRatio = DEFAULT_AMPLITUDE_RATIO;
    private float mWaveLengthRatio = DEFAULT_WAVE_LENGTH_RATIO;
    private float mWaterLevelRatio = DEFAULT_WATER_LEVEL_RATIO;
    private float mWaveShiftRatio = DEFAULT_WAVE_SHIFT_RATIO;


    //被覆盖波浪的颜色
    public static final int DEFAULT_BEHIND_WAVE_COLOR = Color.parseColor("#20FFFFFF");
    //显示在最顶部的波浪颜色
    public static final int DEFAULT_FRONT_WAVE_COLOR = Color.parseColor("#20FFFFFF");
    private int mBehindWaveColor = DEFAULT_BEHIND_WAVE_COLOR;
    private int mFrontWaveColor = DEFAULT_FRONT_WAVE_COLOR;
    // 是否显示波浪
    private boolean isCharge;
    // 重复波浪着色器
    private BitmapShader mWaveShader;
    // 着色器矩阵
    private Matrix mShaderMatrix;
    // 波浪画笔
    private Paint mViewPaint;
    // 圆圈画笔
    private Paint mBorderPaint;
    //默认振幅
    private float mDefaultAmplitude;
    //默认波浪高度
    private float mDefaultWaterLevel;
    //默认波浪长度
    private float mDefaultWaveLength;
    //默认频率
    private double mDefaultAngularFrequency;

    private int padding = 80;
    // 画字体的画笔 剩余电量字体
    private Paint mTextPaint;
    // 画字体的画笔 提示字体
    private Paint tipsPaint;
    private RectF oval1First;
    private Bitmap bitmapWaveCircle;
    private Bitmap bitmapCircleBg;
    //  private Bitmap bitmap3;
    //  private RectF oval1First3;
    private float rotation;
    private float rotationSpeed = 1;//选择速度
    private int percent = 0;
    private float textMarginTop;
    private float textMarginBottom;

    public WaveView(Context context) {
        super(context);
        init();
    }

    public WaveView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public WaveView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    /**
     * 初始化画笔和矩形
     */
    private void init() {
        textMarginTop = getResources().getDimension(R.dimen.circle_margin_top);
        textMarginBottom = getResources().getDimension(R.dimen.circle_margin_bottom);
        mShaderMatrix = new Matrix();
        mViewPaint = new Paint();
        mTextPaint = new Paint();
        mTextPaint.setColor(Color.parseColor("#ffffff"));
        mTextPaint.setTextSize(getResources().getDimension(R.dimen.circle_text_least));
        mViewPaint.setAntiAlias(true);
        tipsPaint = new Paint();
        tipsPaint.setColor(Color.parseColor("#ffffff"));
        tipsPaint.setTextSize(getResources().getDimension(R.dimen.circle_text_tips));
        tipsPaint.setAntiAlias(true);
        //定义波浪外圆的大小
        oval1First = new RectF();
        bitmapWaveCircle = BitmapFactory.decodeResource(getResources(), R.mipmap.bg_white_in_circle);
        //最外层背景
        bitmapCircleBg = BitmapFactory.decodeResource(getResources(), R.mipmap.bg_white_out_circle);
        //电池
        //  bitmap3 = BitmapFactory.decodeResource(getResources(), R.mipmap.b4);
        //  oval1First3 = new RectF();

    }

    /**
     * @param percent 当前电量
     */
    public void setPercent(int percent) {

        this.percent = percent;
        if (percent > 100) {
            this.percent = 100;
        } else if (percent < 0) {
            this.percent = 0;
        }
        Log.e("percent", (float) percent / (float) 100 + "");
        setWaterLevelRatio((float) percent / (float) 100);
    }

    /**
     * 转移率
     * Shift the wave horizontally according to <code>waveShiftRatio</code>.
     *
     * @param waveShiftRatio Should be 0 ~ 1. Default to be 0.
     *                       Result of waveShiftRatio multiples width of WaveView is the length to shift.
     */

    public void setWaveShiftRatio(float waveShiftRatio) {
        if (mWaveShiftRatio != waveShiftRatio) {
            mWaveShiftRatio = waveShiftRatio;

            invalidate();
        }
    }

    public float getWaveShiftRatio() {
        return mWaveShiftRatio;
    }


    /**
     * Set water level according to <code>waterLevelRatio</code>.
     *
     * @param waterLevelRatio Should be 0 ~ 1. Default to be 0.5.
     *                        Ratio of water level to WaveView height.
     *                        波浪高度
     */
    public void setWaterLevelRatio(float waterLevelRatio) {
        if (waterLevelRatio < 0) {
            mWaterLevelRatio = 0f;
        } else if (waterLevelRatio > 1) {
            mWaterLevelRatio = 1f;
        } else {
            mWaterLevelRatio = waterLevelRatio;
        }
        Log.e("mWaterLevelRatio", +mWaterLevelRatio + "");
        invalidate();
    }

    public float getWaterLevelRatio() {
        return mWaterLevelRatio;
    }


    /**
     * Set vertical size of wave according to <code>amplitudeRatio</code>
     *
     * @param amplitudeRatio Default to be 0.05. Result of amplitudeRatio + waterLevelRatio should be less than 1.
     *                       Ratio of amplitude to height of WaveView.
     */
    public void setAmplitudeRatio(float amplitudeRatio) {
        if (mAmplitudeRatio != amplitudeRatio) {
            mAmplitudeRatio = amplitudeRatio;
            invalidate();
        }
    }

    public float getAmplitudeRatio() {
        return mAmplitudeRatio;
    }


    /**
     * Set horizontal size of wave according to <code>waveLengthRatio</code>
     *
     * @param waveLengthRatio Default to be 1.
     *                        Ratio of wave length to width of WaveView.
     */
    public void setWaveLengthRatio(float waveLengthRatio) {
        mWaveLengthRatio = waveLengthRatio;
    }


    public float getWaveLengthRatio() {
        return mWaveLengthRatio;
    }


    public void setWaveColor(int behindWaveColor, int frontWaveColor) {
        mBehindWaveColor = behindWaveColor;
        mFrontWaveColor = frontWaveColor;

        if (getWidth() > 0 && getHeight() > 0) {
            // need to recreate shader when color changed
            mWaveShader = null;
            createShader();
            invalidate();
        }
    }


    public boolean isCharge() {
        return isCharge;
    }

    public void setIsCharge(boolean isCharge) {
        this.isCharge = isCharge;
    }

    public void setBorder(int width, int color) {
        if (mBorderPaint == null) {
            mBorderPaint = new Paint();
            mBorderPaint.setAntiAlias(true);
            mBorderPaint.setStyle(Style.STROKE);
        }
        mBorderPaint.setColor(color);
        mBorderPaint.setStrokeWidth(width);

        invalidate();
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        createShader();
        resetCircleBg();
    }

    /**
     * 创建默认的波浪，横向重复，垂直夹紧的着色器。
     */
    private void createShader() {
        mDefaultAngularFrequency = 2.0f * Math.PI / DEFAULT_WAVE_LENGTH_RATIO / getWidth();
        mDefaultAmplitude = (getHeight()) * DEFAULT_AMPLITUDE_RATIO;
        mDefaultWaterLevel = (getHeight()) * DEFAULT_WATER_LEVEL_RATIO;
        mDefaultWaveLength = getWidth();
        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        //  Bitmap bitmapWaveCircle = BitmapFactory.decodeResource(getResources(), R.mipmap.c);

        Canvas canvas = new Canvas(bitmap);

        Paint wavePaint = new Paint();
        wavePaint.setStrokeWidth(2);
        wavePaint.setAntiAlias(true);

        // Draw default waves into the bitmapWaveCircle
        // y=Asin(ωx+φ)+h
        final int endX = getWidth() + 1;
        final int endY = getHeight() + 1;

        float[] waveY = new float[endX];

        wavePaint.setColor(mBehindWaveColor);
        for (int beginX = 0; beginX < endX; beginX++) {
            double wx = beginX * mDefaultAngularFrequency;
            float beginY = (float) (mDefaultWaterLevel + mDefaultAmplitude * Math.sin(wx));
            canvas.drawLine(beginX, beginY, beginX, endY, wavePaint);

            waveY[beginX] = beginY;
        }

        wavePaint.setColor(mFrontWaveColor);
        final int wave2Shift = (int) (mDefaultWaveLength / 4);
        for (int beginX = 0; beginX < endX; beginX++) {
            canvas.drawLine(beginX, waveY[(beginX + wave2Shift) % endX], beginX, endY, wavePaint);
        }

        // use the bitamp to create the shader
        mWaveShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
        mViewPaint.setShader(mWaveShader);
    }

    /**
     * 定义旋转的圆
     */
    private void resetCircleBg() {
        int width = bitmapCircleBg.getWidth();
        int height = bitmapCircleBg.getHeight();
        // 设置想要的大小
        int newWidth = getWidth() - 40;
        int newHeight = getHeight() - 40;
        // 计算缩放比例
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // 取得想要缩放的matrix参数
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        //重设大小
        // 得到新的图片
        bitmapCircleBg = Bitmap.createBitmap(bitmapCircleBg, 0, 0, width, height, matrix, true);

        oval1First.left = padding;
        oval1First.top = padding;
        oval1First.right = getWidth() - padding;
        oval1First.bottom = getHeight() - padding;

//        oval1First3.left = getWidth() / 2 - bitmap3.getWidth() / 2;
//        oval1First3.top = getHeight() / 2 - bitmap3.getHeight() / 2 + 30;
//        oval1First3.right = getWidth() / 2 + bitmap3.getWidth() / 2;
//        oval1First3.bottom = getHeight() / 2 + bitmap3.getHeight() / 2 + 70;
    }


    @Override
    protected void onDraw(Canvas canvas) {
        // modify paint shader according to isCharge state
        if (mWaveShader != null) {

            // first call after isCharge, assign it to our paint
            if (mViewPaint.getShader() == null) {
                mViewPaint.setShader(mWaveShader);
            }


            // assign matrix to invalidate the shader
            if (isCharge) {
                // sacle shader according to mWaveLengthRatio and mAmplitudeRatio
                // this decides the size(mWaveLengthRatio for width, mAmplitudeRatio for height) of waves
                mShaderMatrix.setScale(
                        mWaveLengthRatio / DEFAULT_WAVE_LENGTH_RATIO,
                        mAmplitudeRatio / DEFAULT_AMPLITUDE_RATIO,
                        0,
                        mDefaultWaterLevel);
                // translate shader according to mWaveShiftRatio and mWaterLevelRatio
                // this decides the start position(mWaveShiftRatio for x, mWaterLevelRatio for y) of waves
                mShaderMatrix.postTranslate(
                        mWaveShiftRatio * getWidth(),
                        (DEFAULT_WATER_LEVEL_RATIO - mWaterLevelRatio) * (getHeight() - padding * 2));

            }
            mWaveShader.setLocalMatrix(mShaderMatrix);
            //圆形波浪
            float radius = getWidth() / 2f - mBorderPaint.getStrokeWidth() - padding;
            canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, radius, mViewPaint);
            //波浪外圆

            canvas.drawBitmap(bitmapWaveCircle, null, oval1First, mBorderPaint);

            //剩余电量字体
            String txtPercent = percent + "%";
            float mTxtWidth = mTextPaint.measureText(txtPercent, 0, txtPercent.length());
            canvas.drawText(txtPercent, getWidth() / 2 - mTxtWidth / 2, getHeight() / 2 - textMarginBottom, mTextPaint);
            //提示字体
            String txtTips;
            if (isCharge) {
                txtTips = "正在充电";
                if (percent == 100) {
                    txtTips = "充电完成";
                }
            } else {
                txtTips = "剩余电量";
            }

            float txtTipsWidth = tipsPaint.measureText(txtTips, 0, txtTips.length());
            canvas.drawText(txtTips, getWidth() / 2 - txtTipsWidth / 2, getHeight() / 2 + textMarginTop, tipsPaint);
            // canvas.drawBitmap(bitmap3, null, oval1First3, mBorderPaint);

            if (rotation == 360) {
                rotation = 0;
            }
            rotation += rotationSpeed;
            //使外层背景旋转
            drawRotateBitmap(canvas, mBorderPaint, bitmapCircleBg, rotation, getWidth() / 2, getHeight() / 2);
        } else {
            mViewPaint.setShader(null);
        }


    }

    /**
     * 绘制自旋转位图
     *
     * @param canvas
     * @param paint
     * @param bitmap   位图对象
     * @param rotation 旋转度数
     * @param posX     在canvas的位置坐标
     * @param posY
     */
    private void drawRotateBitmap(Canvas canvas, Paint paint, Bitmap bitmap,
                                  float rotation, float posX, float posY) {
        Matrix matrix = new Matrix();
        int offsetX = bitmap.getWidth() / 2;
        int offsetY = bitmap.getHeight() / 2;

        matrix.postTranslate(-offsetX, -offsetY);
        if (isCharge) {
            matrix.postRotate(rotation);
        }
        matrix.postTranslate(getWidth() / 2, getHeight() / 2);
        canvas.drawBitmap(bitmap, matrix, paint);
    }

}
